package com.example.shushiyunsst.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.animation.LinearInterpolator;

import androidx.appcompat.widget.AppCompatEditText;
import androidx.core.content.ContextCompat;

import com.example.library_common.utils.ShUtils;
import com.example.shushiyunsst.R;

public class PasswordEditText extends AppCompatEditText {

    private final int EXTRA_TOUCH_AREA = 50;
    private Drawable mHideDrawable;
    private Drawable mShowDrawable;
    private boolean mPasswordVisible = false;
    private boolean touchDown;
    private boolean mShowAsText;
    private String mHideTextString;
    private String mShowTextString;


    public PasswordEditText(Context context) {
        super(context);
    }

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0, 0);
    }


    public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, 0, 0);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.password_edit_text, defStyleAttr, defStyleRes);

        int hideDrawableResId = R.drawable.eye_hid;
        int showDrawableResId = R.drawable.eye_show;
        int drawable_tint = Color.BLACK;
        try {
            drawable_tint = a.getColor(R.styleable.password_edit_text_drawable_tint, drawable_tint);
            mPasswordVisible = a.getBoolean(R.styleable.password_edit_text_password_visible, false);
            hideDrawableResId = a.getResourceId(R.styleable.password_edit_text_hide_drawable, hideDrawableResId);
            showDrawableResId = a.getResourceId(R.styleable.password_edit_text_show_drawable, showDrawableResId);
            mShowAsText = a.getBoolean(R.styleable.password_edit_text_show_as_text, false);
            if (mShowAsText) {
                mShowTextString = a.getString(R.styleable.password_edit_text_show_text);
                mHideTextString = a.getString(R.styleable.password_edit_text_hide_text);
            }
        } finally {
            a.recycle();

            mHideDrawable = ShUtils.tintDrawable(hideDrawableResId, drawable_tint);
            mShowDrawable = ShUtils.tintDrawable(showDrawableResId, drawable_tint);
//            mHideDrawable = ContextCompat.getDrawable(context, hideDrawableResId);
//            mShowDrawable = ContextCompat.getDrawable(context, showDrawableResId);
            if (mShowAsText) {
                mHideTextString = TextUtils.isEmpty(mHideTextString) ? context.getString(R.string.hide_text) : mHideTextString;
                mShowTextString = TextUtils.isEmpty(mShowTextString) ? context.getString(R.string.show_text) : mShowTextString;
            }
        }

        mHideDrawable.setBounds(0, 0, mHideDrawable.getIntrinsicWidth(), mHideDrawable.getIntrinsicHeight());
        mShowDrawable.setBounds(0, 0, mShowDrawable.getIntrinsicWidth(), mShowDrawable.getIntrinsicHeight());
        if (mPasswordVisible) {
            showPassword();
        } else {
            hidePassword();
        }
    }


    private void togglePasswordView() {
        if (mPasswordVisible) {
            hidePassword();
        } else {
            showPassword();
        }
    }

    private void showPassword() {
        if (mShowAsText) {
            setCompoundDrawables(null, null, new TextDrawable(mHideTextString), null);
        } else {
            setCompoundDrawables(null, null, mShowDrawable, null);
        }
//        setInputType(InputType.TYPE_CLASS_TEXT |InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
        setTransformationMethod(HideReturnsTransformationMethod.getInstance());
        Editable text = getText();
        if (text != null) {
            setSelection(getText().length());
        }
        mPasswordVisible = true;
    }

    private void hidePassword() {
        if (mShowAsText) {
            setCompoundDrawables(null, null, new TextDrawable(mShowTextString), null);
        } else {
            setCompoundDrawables(null, null, mHideDrawable, null);
        }
//        setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        setTransformationMethod(PasswordTransformationMethod.getInstance());
        Editable text = getText();
        if (text != null) {
            setSelection(getText().length());
        }
        mPasswordVisible = false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getCompoundDrawables()[2] != null) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                Rect rect = getCompoundDrawables()[2].getBounds();
                int height = rect.height();
                int distance = (getHeight() - height) / 2;
                boolean isInnerWidth = x > (getWidth() - getTotalPaddingRight()) && x < (getWidth() - getPaddingRight());
                boolean isInnerHeight = y > distance && y < (distance + height);
                if (isInnerWidth && isInnerHeight) {
                    togglePasswordView();
                }
            }
        }
        return super.onTouchEvent(event);
    }

    @Override
    public Parcelable onSaveInstanceState() {
        Parcelable saveState = super.onSaveInstanceState();
        return new SavedState(saveState, mPasswordVisible);
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {

        SavedState savedState = (SavedState) state;

        mPasswordVisible = savedState.isPasswordVisible();
        if (mPasswordVisible) {
            showPassword();
        } else {
            hidePassword();
        }
        super.onRestoreInstanceState(savedState.getSuperState());
    }

    private static class SavedState extends BaseSavedState {

        private boolean isPasswordVisible = false;

        public SavedState(Parcel source) {
            super(source);
            isPasswordVisible = source.readByte() != 0;
        }

        public SavedState(Parcelable superState, boolean passwordVisible) {
            super(superState);
            isPasswordVisible = passwordVisible;
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeByte((byte) (isPasswordVisible == true ? 1 : 0));
        }

        public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {

            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }

        };

        public boolean isPasswordVisible() {
            return isPasswordVisible;
        }
    }

    private class TextDrawable extends Drawable {
        private String mText;
        private ColorStateList mPrefixTextColor;

        public TextDrawable(String text) {
            mText = text;
            mPrefixTextColor = getTextColors();
            setBounds(0, 0, (int) getPaint().measureText(mText), (int) getTextSize());
        }

        @Override
        public void draw(Canvas canvas) {
            Paint paint = getPaint();

            paint.setColor(mPrefixTextColor.getColorForState(getDrawableState(), 0));
            int lineBaseline = getLineBounds(0, null);
            canvas.drawText(mText, 0, canvas.getClipBounds().top + lineBaseline, paint);
        }

        @Override
        public void setAlpha(int alpha) {/* Not supported */}

        @Override
        public void setColorFilter(ColorFilter colorFilter) {/* Not supported */}

        @Override
        public int getOpacity() {
            return PixelFormat.OPAQUE;
        }
    }
}